Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald-tests\analysissensor-tests.cpp
Line
Count
Source
1
//  Copyright 2021 Herald project contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#include "test-templates.h"
6
7
#include "catch.hpp"
8
9
#include "herald/herald.h"
10
11
#include <utility>
12
#include <iostream>
13
14
using namespace herald;
15
using namespace herald::analysis::sampling;
16
using namespace herald::datatype;
17
18
struct DummyDistanceDelegate {
19
  using value_type = Distance;
20
21
  DummyDistanceDelegate() : lastSampledID(0), distances() {};
22
  DummyDistanceDelegate(const DummyDistanceDelegate&) = delete; // copy ctor deleted
23
  DummyDistanceDelegate(DummyDistanceDelegate&& other) noexcept : lastSampledID(other.lastSampledID), distances(std::move(other.distances)) {} // move ctor
24
  ~DummyDistanceDelegate() {};
25
26
  DummyDistanceDelegate& operator=(DummyDistanceDelegate&& other) noexcept {
27
    lastSampledID = other.lastSampledID;
28
    std::swap(distances,other.distances);
29
    return *this;
30
  }
31
32
  // specific override of template
33
  void newSample(SampledID sampled, Sample<Distance> sample) {
34
    lastSampledID = sampled;
35
    distances.push(sample);
36
  }
37
38
  void reset() {
39
    distances.clear();
40
    lastSampledID = 0;
41
  }
42
43
  // Test only methods
44
  SampledID lastSampled() {
45
    return lastSampledID;
46
  }
47
48
  const SampleList<Sample<Distance>,25>& samples() {
49
    return distances;
50
  }
51
52
private:
53
  SampledID lastSampledID;
54
  SampleList<Sample<Distance>,25> distances;
55
};
56
57
/// [Who]   As a DCT app developer
58
/// [What]  I want to link my live application data to an analysis runner easily
59
/// [Value] So I don't have to write plumbing code for Herald itself
60
/// 
61
/// [Who]   As a DCT app developer
62
/// [What]  I want to periodically run analysis aggregates automatically
63
/// [Value] So I don't miss any information, and have accurate, regular, samples
64
1
TEST_CASE("analysissensor-rssi-basic", "[analysissensor][rssi][basic]") {
65
1
  SECTION("analysissensor-rssi-basic") {
66
1
    Proximity p1{.unit = ProximityMeasurementUnit::RSSI, .value = -55};
67
1
    Proximity p2{.unit = ProximityMeasurementUnit::RSSI, .value = -56};
68
1
    Proximity p3{.unit = ProximityMeasurementUnit::RSSI, .value = -57};
69
1
    Proximity p4{.unit = ProximityMeasurementUnit::RSSI, .value = -58};
70
1
71
1
    herald::analysis::algorithms::distance::FowlerBasicAnalyser distanceAnalyser(0, -50, -24); // 0 = run every time run() is called
72
1
73
1
    DummyDistanceDelegate myDelegate;
74
1
    herald::analysis::AnalysisDelegateManager adm(std::move(myDelegate)); // NOTE: myDelegate MOVED FROM and no longer accessible
75
1
    herald::analysis::AnalysisProviderManager apm(std::move(distanceAnalyser)); // NOTE: distanceAnalyser MOVED FROM and no longer accessible
76
1
77
1
    herald::analysis::AnalysisRunner<
78
1
      herald::analysis::AnalysisDelegateManager<DummyDistanceDelegate>,
79
1
      herald::analysis::AnalysisProviderManager<herald::analysis::algorithms::distance::FowlerBasicAnalyser>,
80
1
      RSSI,Distance
81
1
    > runner(adm, apm); // just for Sample<RSSI> types, and their produced output (Sample<Distance>)
82
1
83
1
    herald::analysis::SensorDelegateRSSISource<decltype(runner)> src(runner);
84
1
    PayloadData payload(std::byte(5),4);
85
1
    TargetIdentifier id(Data(std::byte(3),16));
86
1
    src.sensor(SensorType::BLE, p1, id, payload);
87
1
    src.sensor(SensorType::BLE, p2, id, payload);
88
1
    runner.run(Date()); // In an app, use a Coordinator task
89
1
    src.sensor(SensorType::BLE, p3, id, payload);
90
1
    src.sensor(SensorType::BLE, p4, id, payload);
91
1
    runner.run(Date()); // In an app, use a Coordinator task
92
1
93
1
    auto& delegateRef = adm.get<DummyDistanceDelegate>();
94
1
    REQUIRE(delegateRef.lastSampled() != 0);
95
1
96
1
    auto& samples = delegateRef.samples();
97
1
    REQUIRE(samples.size() == 1); // Only 1 because time will run in 'real time' as its a sensor source (dynamic date)
98
1
    REQUIRE(samples[0].taken.secondsSinceUnixEpoch() != 0);
99
1
    REQUIRE(samples[0].value != 0.0);
100
1
101
1
    // Let's see the total memory in use...
102
1
    std::cout << "AnalysisRunner::RAM = " << sizeof(runner) << std::endl;
103
1
    std::cout << "SensorDelegateRSSISource::RAM = " << sizeof(src) << std::endl;
104
1
  }
105
1
}
106
107
108
109
1
TEST_CASE("analysissensor-output", "[sensorlogger][analysissensor][output]") {
110
1
  SECTION("analysissensor-output") {
111
1
    DummyLoggingSink dls;
112
1
    DummyBluetoothStateManager dbsm;
113
1
    herald::DefaultPlatformType dpt;
114
1
    herald::Context ctx(dpt,dls,dbsm); // default context include
115
1
    using CT = typename herald::Context<herald::DefaultPlatformType,DummyLoggingSink,DummyBluetoothStateManager>;
116
1
    //herald::data::SensorLogger logger(ctx,"testout","analysissensor");
117
1
    herald::analysis::LoggingAnalysisDelegate<CT,Distance> lad(ctx); // The subject of this test
118
1
    std::cout << "LoggingAnalysisDelegate::RAM = " << sizeof(lad) << std::endl;
119
1
120
1
    
121
1
    Proximity p1{.unit = ProximityMeasurementUnit::RSSI, .value = -55};
122
1
    Proximity p2{.unit = ProximityMeasurementUnit::RSSI, .value = -56};
123
1
    Proximity p3{.unit = ProximityMeasurementUnit::RSSI, .value = -57};
124
1
    Proximity p4{.unit = ProximityMeasurementUnit::RSSI, .value = -58};
125
1
126
1
    herald::analysis::algorithms::distance::FowlerBasicAnalyser distanceAnalyser(0, -50, -24); // 0 = run every time run() is called
127
1
128
1
    DummyDistanceDelegate myDelegate;
129
1
    herald::analysis::AnalysisDelegateManager adm(std::move(myDelegate), std::move(lad)); // NOTE: myDelegate MOVED FROM and no longer accessible
130
1
    herald::analysis::AnalysisProviderManager apm(std::move(distanceAnalyser)); // NOTE: distanceAnalyser MOVED FROM and no longer accessible
131
1
132
1
    herald::analysis::AnalysisRunner<
133
1
      herald::analysis::AnalysisDelegateManager<DummyDistanceDelegate,herald::analysis::LoggingAnalysisDelegate<CT,Distance>>,
134
1
      herald::analysis::AnalysisProviderManager<herald::analysis::algorithms::distance::FowlerBasicAnalyser>,
135
1
      RSSI,Distance
136
1
    > runner(adm, apm); // just for Sample<RSSI> types, and their produced output (Sample<Distance>)
137
1
138
1
    herald::analysis::SensorDelegateRSSISource<decltype(runner)> src(runner);
139
1
    PayloadData payload(std::byte(5),4);
140
1
    TargetIdentifier id(Data(std::byte(3),16));
141
1
    src.sensor(SensorType::BLE, p1, id, payload);
142
1
    src.sensor(SensorType::BLE, p2, id, payload);
143
1
    runner.run(Date()); // In an app, use a Coordinator task
144
1
    src.sensor(SensorType::BLE, p3, id, payload);
145
1
    src.sensor(SensorType::BLE, p4, id, payload);
146
1
    runner.run(Date()); // In an app, use a Coordinator task
147
1
148
1
    auto& delegateRef = adm.get<DummyDistanceDelegate>();
149
1
    REQUIRE(delegateRef.lastSampled() != 0);
150
1
151
1
    auto& samples = delegateRef.samples();
152
1
    REQUIRE(samples.size() == 1); // Only 1 because time will run in 'real time' as its a sensor source (dynamic date)
153
1
    REQUIRE(samples[0].taken.secondsSinceUnixEpoch() != 0);
154
1
    REQUIRE(samples[0].value != 0.0);
155
1
156
1
    auto lastMsg = dls.value;
157
1
    REQUIRE(lastMsg != ""); // must have logged something...
158
1
    std::cout << "Last log message: " << lastMsg << std::endl;
159
1
160
1
    // Let's see the total memory in use...
161
1
    std::cout << "AnalysisRunner::RAM = " << sizeof(runner) << std::endl;
162
1
    std::cout << "SensorDelegateRSSISource::RAM = " << sizeof(src) << std::endl;
163
1
164
1
165
1
  }
166
1
}